/* EasyWay Game Engine
 * Copyright (C) 2006 Daniele Paggi.
 *  
 * Written by: 2006 Daniele Paggi<dshnt@hotmail.com>
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.easyway.system;

import org.lwjgl.opengl.Display;

/**
 * @author Daniele Paggi
 * 
 */
class Sincro extends Thread {

	/** indicates if the game is looping or not */
	static boolean loop = true;

	/** game's frame per second */
	static int fps = 60;

	/**
	 * timeOut
	 * 
	 * @see Core.setTimeOut(int)
	 */
	protected int timeOut = 10000;

	/** reference to the Game Core */
	protected Core core;

	/** reference to the TOOC */
	private TimeOutOpController tc = null;

	{
		loop = true;
		core = StaticRef.core;
	}

	/** main loop of game */
	public void run() {
		core.init(); // creation
		last = System.nanoTime();// currentTimeMillis();
		CurrentTime = LastTime = System.nanoTime();// currentTimeMillis();
		ElaspedTime = 0;

		if (timeOut >= 1000) {
			tc = new TimeOutOpController(timeOut, this);
			tc.start();
		}
		if (Display.isCreated()) {
			core.creation();
			while (loop) {
				if (Display.isCloseRequested()) {// close on ALT + F4
					core.endGame(); // loop = false
				}
				ricaveElaspedTime();
				if (tc != null) {
					tc.stateA();
				}
				core.coreLoop();
				core.coreRender();
				if (tc != null) {
					tc.stateB();
				}

				Display.sync(fps); // speed down the loop
				Display.update(); // draw at screen
				// calculates the fps
				fps();
			}
		} else {
			while (loop) {
				ricaveElaspedTime();
				if (tc != null) {
					tc.stateA();
				}
				core.internalWindow.repaint();
				if (tc != null) {
					tc.stateB();
				}

				Display.sync(fps); // speed down the loop

				// calculates the fps
				fps();
			}

		}
		core.cleanup();
	}

	/** used for the fps */
	protected int cont = 0, lastFps = 100;

	/** last time: used for calculate the fps */
	protected long last;

	/** calculate the fps */
	protected void fps() {
		++cont;
		if (System.nanoTime()- last >= 1000000000L) {
			lastFps = cont;
			cont = 0;
			last = System.nanoTime();
		}
	}

	/** returns how much FPS has got the Game in the last cycle */
	public int getFps() {
		return lastFps;
	}

	protected long LastTime, CurrentTime, ElaspedTime;

	/** calculates the elasped time */
	protected void ricaveElaspedTime() {
		LastTime = CurrentTime;
		CurrentTime = System.nanoTime();// .currentTimeMillis();
		ElaspedTime = CurrentTime - LastTime;
	}

	/** returns the elasped time */
	public long getElaspedTime() {
		return ElaspedTime;
	}

	/** returns the Time out */
	public int getTimeOut() {
		return timeOut;
	}

	/**
	 * sets the time out
	 * 
	 * @param timeOut
	 *            time in ms
	 */
	public void setTimeOut(int timeOut) {
		this.timeOut = timeOut;
		if (timeOut > 1000) {
			tc = new TimeOutOpController(timeOut, this);
			tc.start();
		} else {
			if (tc!=null)
				tc.stop();
			tc = null;
		}
	}

}
